package com.ruoyi.statement.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.base.service.impl.SSerialServiceImpl;
import com.ruoyi.business.projectRecord.domain.ProjectRecord;
import com.ruoyi.business.projectRecord.mapper.ProjectRecordMapper;
import com.ruoyi.common.annotation.CompanyScope;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.finance.collection.domain.BillCollection;
import com.ruoyi.finance.collection.mapper.BillCollectionMapper;
import com.ruoyi.finance.collection.service.impl.BillCollectionServiceImpl;
import com.ruoyi.statement.domain.BillStatement;
import com.ruoyi.statement.mapper.BillStatementMapper;
import com.ruoyi.statement.service.IBillStatementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author fuzhen-pc
 * @description TODO
 * @date 2023/6/25 15:36
 */
@Service
public class BillStatementServiceImpl extends ServiceImpl<BillStatementMapper, BillStatement> implements IBillStatementService {

    @Autowired
    BillStatementMapper billStatementMapper;
    
    @Autowired
    BillCollectionMapper billCollectionMapper;
    
    @Autowired
    ProjectRecordMapper projectRecordMapper;

    @Autowired
    BillCollectionServiceImpl billCollectionService;

    @Autowired
    SSerialServiceImpl sSerialService;

    /**
     * @param billCollectionIdS
     * @return
     * @description 生成对账单
     */
    @Override
    public AjaxResult generateBillStatement(List<Long> billCollectionIdS) {
        //获取收款费项列表
        List<BillCollection> billCollections = billCollectionService.listByIds(billCollectionIdS);

        if(billCollections.size() > 0){
            //判断是否有已经生成对账单的费项，有则返回，没有获取idList
            for (BillCollection bl : billCollections) {
                if (!bl.getCollectionStatus().equals("0") && bl.getDelFlag().equals("0")) {
                    return AjaxResult.error("存在已生成对账单的费项，不能生成对账单。");
                }
            }


            //新增对账单
            BillCollection billCollection = billCollections.get(0);
            BillStatement billStatement = new BillStatement();
            billStatement.setCustomerCod(billCollection.getCustomerCod());
            billStatement.setCustomerNam(billCollection.getCustomerNam());
            billStatement.setStatementNo(sSerialService.getSerialNumberByCodeDept("STA_COL_NO",billCollection.getCompanyCod()));
            billStatement.setCreateBy(SecurityUtils.getUsername());
            if(this.save(billStatement)){
                //再次校验费项状态，防止因函数处理时间过长导致前端无结果反馈时，用户重复进行“对账”操作，生成状态错误的多余的对账单的情况
                List<BillCollection> billCollectionsValid = billCollectionService.listByIds(billCollectionIdS);
                for (BillCollection bcValid : billCollectionsValid) {
                    if (!bcValid.getCollectionStatus().equals("0") && bcValid.getDelFlag().equals("0")) {
                        throw new RuntimeException("对账单正在生成中，请勿重复操作！" );
                    }
                }
                //更新费项对账单号
                UpdateWrapper<BillCollection> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda().set(BillCollection::getStatementId, billStatement.getBillStatementId());
                updateWrapper.lambda().set(BillCollection::getCollectionStatus, "1");
                updateWrapper.lambda().in(BillCollection::getBillCollectionId, billCollectionIdS);
                if (!billCollectionService.update(updateWrapper)){
                    throw new RuntimeException("生成失败" );
                }
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("flag", 0);
                jsonObject.put("msg", "");
                jsonObject.put("companyCode", billCollection.getCompanyCod());
//                jsonObject.put("billCollectionIds", billCollectionIdS.stream().map(String::valueOf).collect(Collectors.joining(",")));
                //调用distinguishBillCollectionIds去除billCollectionIdS中业务数据重复的Id，减少输入P_GEN_STATEMENT的参数量
                //后续新增业务类型时需要对distinguishBillCollectionIds函数的逻辑进行相应调整
                String uniqueBillCollectionIds = billCollectionService.distinguishBillCollectionIds(billCollectionIdS,billCollection.getCompanyCod());
                jsonObject.put("billCollectionIds", uniqueBillCollectionIds);
                billStatementMapper.P_GEN_STATEMENT(jsonObject);
                if (jsonObject.getIntValue("flag") == 0){
                    throw new RuntimeException("生成失败:" + jsonObject.getString("msg"));
                }
                return AjaxResult.success("生成对账单成功。",billStatement);
            }

        }
        return AjaxResult.error("费项不存在。");
    }


    @Override
    public List<BillStatement> selectBillStatementList(BillStatement billStatement) {
        //  按照搜索条件查询
        QueryWrapper<BillStatement> billStatementQueryWrapper = new QueryWrapper<>();
        billStatementQueryWrapper.eq("DEL_FLAG","0");
        billStatementQueryWrapper.eq(StringUtils.isNotEmpty(billStatement.getStatementNo()),"STATEMENT_NO",billStatement.getStatementNo());
        billStatementQueryWrapper.like(StringUtils.isNotEmpty(billStatement.getCustomerNam()),"CUSTOMER_NAM",billStatement.getCustomerNam());
        billStatementQueryWrapper.eq(StringUtils.isNotEmpty(billStatement.getStatementStatus()),"STATEMENT_STATUS",billStatement.getStatementStatus());
        billStatementQueryWrapper.orderByDesc("CREATE_TIME");
        billStatementQueryWrapper.orderByDesc("STATEMENT_STATUS");
        List<BillStatement> billStatements = baseMapper.selectList(billStatementQueryWrapper);
        
        for (BillStatement currBillStatement : billStatements) {
            // 根据billStatementId查询billCollection表中的数据，获取该对账单下具体的费项数据列表
            QueryWrapper<BillCollection> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BillCollection::getStatementId, currBillStatement.getBillStatementId());
            queryWrapper.lambda().eq(BillCollection::getDelFlag, "0");
            List<BillCollection> billCollections = billCollectionMapper.selectList(queryWrapper);
            
            // 累加费项金额，并设置到对账单对象中
            BigDecimal sumAmount = billCollections.stream().map(BillCollection::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            currBillStatement.setSumAmount(sumAmount);
            
            // 根据费项数据列表中每个元素的币别，并设置到对账单对象中
            List<String> currencyList = billCollections.stream().map(BillCollection::getCurrency).distinct().collect(Collectors.toList());
            String currencyStr = String.join(",", currencyList);
            currBillStatement.setCurrency(currencyStr);

            // 根据费项数据列表中每个元素的projectId，查询PROJECT_RECORD表中的业务信息描述projectData，拼接成字符串
            List<Long> projectIds = billCollections.stream().map(BillCollection::getProjectId).collect(Collectors.toList());
            QueryWrapper<ProjectRecord> projectRecordQueryWrapper = new QueryWrapper<>();
            if (projectIds.size()!=0){
                projectRecordQueryWrapper.in("PROJECT_ID",projectIds);
                projectRecordQueryWrapper.eq("DEL_FLAG","0");
                List<ProjectRecord> projectRecords = projectRecordMapper.selectList(projectRecordQueryWrapper);
                // 将业务信息描述拼接成字符串，并设置到对账单对象中
                String projectDataStr = projectRecords.stream()
                        .map(projectRecord -> projectRecord.getProjectTypeName() + "：" + projectRecord.getProjectData())
                        .collect(Collectors.joining(";\n"));
                currBillStatement.setProjectData(projectDataStr);
            }
        }
        
        return billStatements;
    }

    @Override
    public AjaxResult cancelBillStatement(Long billStatementId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("flag", 0);
        jsonObject.put("msg", "");
        jsonObject.put("billStatementId", billStatementId);
        billStatementMapper.P_CANCEL_STATEMENT(jsonObject);
        if (jsonObject.getIntValue("flag") == 0){
            throw new RuntimeException("删除对账失败:" + jsonObject.getString("msg"));
        }
        billStatementMapper.updateDelTimeAndDelName(billStatementId,DateUtils.getNowDate(),SecurityUtils.getUsername());
        //取消对账单 1、删除费项表中对账单数据
        baseMapper.deleteBillStatementByStatementId(billStatementId);
        //2、删除
        baseMapper.deleteById(billStatementId);
        return AjaxResult.success("取消成功。");
    }

    @Override
    public void updateBillStatementStatus(Long billStatementId, String statementStatus) {
        // 获取当前的用户名称
        String confirmName = SecurityUtils.getUsername();
        // 获取确认操作时间
        Date confirmTime= DateUtils.getNowDate();

        baseMapper.updateBillStatementStatus(billStatementId,statementStatus,confirmName,confirmTime);

//        确认对账
        String confirmStatus = "1";
        if (confirmStatus.equals(statementStatus)){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("flag", 0);
            jsonObject.put("msg", "");
            jsonObject.put("billStatementId", billStatementId);
            billStatementMapper.P_CHRG_FINISHED(jsonObject);
            if (jsonObject.getIntValue("flag") == 0){
                throw new RuntimeException("确认对账失败:" + jsonObject.getString("msg"));
            }
        }
        if (statementStatus.equals("1")){
            billCollectionMapper.updateCollectionStatus(billStatementId,"2");
        } else if (statementStatus.equals("2")) {
            billCollectionMapper.updateCollectionStatus(billStatementId,"3");
        }
    }
}
